package com.faithbj.common.dao.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Repository;

import com.faithbj.common.configuration.Pager;
import com.faithbj.common.configuration.Pager.OrderType;
import com.faithbj.common.dao.UserDao;
import com.faithbj.common.model.Region;
import com.faithbj.common.model.User;
import com.faithbj.common.dao.RegionDao;

/**
 * @author jrn E-mail: rinanjin@gmail.com
 * @version 0.1 创建时间：2012-6-4 下午09:24:01 类说明
 */
@Repository("userDao")
public class UserDaoImpl extends BaseDaoImpl<User, String> implements UserDao
{
	@Resource
	private RegionDao regionDao;
	
	@Override
	public User getUserByUsername(String username)
	{
		Session session = this.getSession();
		Criteria criteria = session.createCriteria(User.class);
		criteria.add(Restrictions.eq("username", username));
		@SuppressWarnings("unchecked")
		List<User> list = criteria.list();
		if (list.size() > 0)
		{
			return list.get(0);
		}
		return null;
	}
	
	@Override
	public Pager findByPager(Pager pager, DetachedCriteria detachedCriteria)
	{
		if (pager == null)
		{
			pager = new Pager();
		}
		Integer pageNumber = pager.getPageNumber();
		Integer pageSize = pager.getPageSize();
		String property = pager.getProperty();
		String keyword = pager.getKeyword();
		String orderBy = pager.getOrderBy();
		OrderType orderType = pager.getOrderType();

		List<String> propertyList = pager.getPropertyList();
		List<Object> keywordList = pager.getKeywordList();
		List<String> compareTypeList = pager.getCompareTypeList();

		Criteria criteria = detachedCriteria
				.getExecutableCriteria(getSession());
		if (StringUtils.isNotEmpty(property) && StringUtils.isNotEmpty(keyword))
		{
			String propertyString = "";
			if (property.contains("."))
			{
				String propertyPrefix = StringUtils.substringBefore(property,
						".");
				String propertySuffix = StringUtils.substringAfter(property,
						".");
				criteria.createAlias(propertyPrefix, "model");
				propertyString = "model." + propertySuffix;
			} else
			{
				propertyString = property;
			}
			criteria.add(Restrictions.like(propertyString, "%" + keyword + "%"));
		}
		if (propertyList != null && !propertyList.isEmpty()
				&& keywordList != null && !keywordList.isEmpty()
				&& propertyList.size() == keywordList.size())
		{
			for (int i = 0; i < propertyList.size(); i++)
			{
				String propertyString = "";
				if (propertyList.get(i).contains("."))
				{
					String propertyPrefix = StringUtils.substringBefore(
							propertyList.get(i), ".");
					String propertySuffix = StringUtils.substringAfter(
							propertyList.get(i), ".");
					criteria.createAlias(propertyPrefix, "model");
					propertyString = "model." + propertySuffix;
				} else
				{
					propertyString = propertyList.get(i);
				}
				if ("eq".equals(compareTypeList.get(i)))
				{
					criteria.add(Restrictions.eq(propertyString,
							keywordList.get(i)));
				} 
				else if("ge".equals(compareTypeList.get(i)))
				{
					criteria.add(Restrictions.ge(propertyString, keywordList.get(i)));
				}
				else if("le".equals(compareTypeList.get(i)))
				{
					criteria.add(Restrictions.le(propertyString, keywordList.get(i)));
				}
				else
				{
					criteria.add(Restrictions.like(propertyString, "%"
							+ keywordList.get(i) + "%"));
				}
			}
		}

		Long totalCount = (Long) criteria.setProjection(Projections.rowCount())
				.uniqueResult();
		List<String> regionIds = new ArrayList<String>();
		Object userObject = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		if (userObject instanceof User)
		{
			User user = (User) userObject;
			Region region = user.getRegion();
			if(!user.getUsername().equals("super"))
			{
				if(region != null)
				{
					getRegionIds(regionIds, region);
				}
				criteria.add(Restrictions.in("region.id", regionIds));
			}
		}
		criteria.setProjection(null);
		criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
		criteria.setFirstResult((pageNumber - 1) * pageSize);
		criteria.setMaxResults(pageSize);
		if (StringUtils.isNotEmpty(orderBy) && orderType != null)
		{
			if (orderType == OrderType.asc)
			{
				criteria.addOrder(Order.asc(orderBy));
			} else
			{
				criteria.addOrder(Order.desc(orderBy));
			}
		}
		pager.setTotalCount(totalCount.intValue());
		pager.setResult(criteria.list());
		return pager;
	}
	
	private void getRegionIds(List<String> regionIds, Region region)
	{
		regionIds.add(region.getId());
		List<Region> children = regionDao.findAny("from Region where parent.id=?", region.getId());
		if(children != null)
		{
			for(Region r : children)
			{
				getRegionIds(regionIds, r);
			}
		}
	}
}
